﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Intelligent.OTC.Common.UnitOfWork;
using Intelligent.OTC.Domain.DataModel;
using Intelligent.OTC.Domain.Repositories;
using System.Configuration;
using System.IO;
using Intelligent.OTC.Domain;
using Intelligent.OTC.Common;
using System.Data.Entity.Validation;
using Intelligent.OTC.Common.Utils;
using System.Data.Entity;
using System.Transactions;
using EntityFramework.BulkInsert.Extensions;
using Intelligent.OTC.Common.Exceptions;

namespace Intelligent.OTC.Business
{
    public class ContactService
    {
       public OTCRepository CommonRep { private get; set; }

       public int CurrentPeriod
       {
           get
           {
               return CommonRep.GetDbSet<PeriodControl>().Where(o => o.Deal == AppContext.Current.User.Deal).Max(o => o.Id);
           }
       }

        /// <summary>
        /// Delete contact for the given Id
        /// </summary>
        /// <param name="id"></param>
        public void DeleteContact(int id)
        {
            AssertUtils.IsTrue(id > 0, "Contact Id");

            Contactor old = CommonRep.FindBy<Contactor>(id);
            if (old != null)
            {
                CommonRep.Remove(old);
                CommonRep.Commit();
            }
        }

        public void AddOrUpdateContact(Contactor cont)
        {
            try
            {
                Customer cust;
                //新添加contactor
                if (cont.Id == 0)
                {
                    //添加Group级别，如果Group级别但没有对应Group抛出提示，如果有Group备份CustomerNum当降
                    //到Customer级别时，通过BkCustomerNum赋值给CustomerNum
                    if (cont.IsGroupLevel == 1)
                    {
                        cust = CommonRep.GetQueryable<Customer>().Where(o => o.CustomerNum == cont.CustomerNum && o.Deal == AppContext.Current.User.Deal).FirstOrDefault();
                        if (string.IsNullOrEmpty(cust.BillGroupCode))
                        {
                            throw new OTCServiceException("This Customer Doesn't Have Group!");
                        }
                        cont.GroupCode = cust.BillGroupCode;
                        //  cont.BkCustomerNum = cont.CustomerNum;
                        cont.CustomerNum = "";
                        CommonRep.Add(cont);
                    }
                    else
                    {
                        //    cont.BkCustomerNum = cont.CustomerNum;
                        CommonRep.Add(cont);
                    }
                }
                else
                {
                    if (cont.IsGroupLevel == 1)
                    {
                        //if (cont.CustomerNum != "")
                        //{
                        //    cont.BkCustomerNum = cont.CustomerNum;
                        //}
                        cust = CommonRep.GetQueryable<Customer>().Where(o => o.CustomerNum == cont.CustomerNum && o.Deal == AppContext.Current.User.Deal).FirstOrDefault();
                        if (string.IsNullOrEmpty(cust.BillGroupCode))
                        {
                            throw new OTCServiceException("This Customer Doesn't Have Group!!");
                        }
                        cont.GroupCode = cust.BillGroupCode;
                        cont.CustomerNum = "";
                    }
                    else
                    {
                        //  cont.CustomerNum = cont.BkCustomerNum;
                        cont.GroupCode = "";
                    }
                    Contactor old = CommonRep.FindBy<Contactor>(cont.Id);
                    ObjectHelper.CopyObjectWithUnNeed(cont, old, new string[] { "Id", "Customer" });
                }
                CommonRep.Commit();
            }
            catch (OTCServiceException ex)
            {
                Helper.Log.Info(ex);
                throw new OTCServiceException(ex.Message);
            }
            catch (Exception ex)
            {
                Helper.Log.Info(ex);
                throw new Exception(ex.Message);
            }
        }
        
        // Get all Contactors in one group  
        public List<Contactor> GetGroupContactors(string custNum)
        {
            Customer cust = CommonRep.GetQueryable<Customer>().Where(o => o.CustomerNum == custNum && o.Deal == AppContext.Current.User.Deal).FirstOrDefault();
            string billGroupCode=cust.BillGroupCode;
            List<Contactor> contlist = new List<Contactor>();
            if (!string.IsNullOrEmpty(billGroupCode))
            {
                contlist = CommonRep.GetQueryable<Contactor>().Where(o => o.GroupCode == billGroupCode && o.Deal == AppContext.Current.User.Deal).ToList();
                foreach(Contactor cont in contlist)
                {
                    cont.IsGroupLevel = 1;
                }
            }
            return contlist;
        }

        public List<Contactor> GetCustlevelContactors(string custNum) 
        {
            return CommonRep.GetQueryable<Contactor>().Where(o => o.CustomerNum == custNum && o.Deal == AppContext.Current.User.Deal).ToList();
        }

        /// <summary>
        /// Get all contacts for the giving specific customer
        /// </summary>
        /// <param name="strCustNum"></param>
        /// <returns></returns>
        public IList<Contactor> GetContactByCustomer(string strCustNum)
        {
            AssertUtils.ArgumentHasText(strCustNum, "Customer");
         //   return CommonRep.GetQueryable<Contactor>().Where(o => o.CustomerNum == strCustNum && o.Deal == AppContext.Current.User.Deal).ToList();
            List<Contactor> contlist = new List<Contactor>();
            contlist = GetCustlevelContactors(strCustNum);
            if(strCustNum!="newCust"){
                List <Contactor> custlvlist =  GetGroupContactors(strCustNum);
                contlist.AddRange(custlvlist);
                return contlist;
            }
            return contlist;
        }

        /// <summary>
        /// Get all contacts for giving customers
        /// added by zhangYu,get the customer contactor
        /// </summary>
        /// <param name="strCustNums"></param>
        /// <returns></returns>
        public IList<Contactor> GetContactsByCustomers(string strCustNums)
        {
            AssertUtils.ArgumentHasText(strCustNums, "Customers");

             string[] cusArray = strCustNums.Split(',');
            List<Contactor> listContactor  =new List<Contactor>();
            listContactor= (from con in CommonRep.GetQueryable<Contactor>()
                            where con.Deal == AppContext.Current.User.Deal && 
                                  con.IsDefaultFlg == "1"&&
                                  cusArray.Contains(con.CustomerNum) 
                            select con).Distinct().ToList<Contactor>();
            List<Contactor> grouplvlist = GetContactsByGroup(cusArray);
            listContactor.AddRange(grouplvlist);
            return listContactor;
        }

        public List<Contactor> GetContactsByGroup(string[] cusArray)
        {
            List<string> grouplist = new List<string>();
            grouplist=(from cust in CommonRep.GetQueryable<Customer>()
                       where cust.Deal == AppContext.Current.User.Deal &&
                             cusArray.Contains(cust.CustomerNum) && cust.BillGroupCode!=null
                       select cust.BillGroupCode).Distinct().ToList<string>();
            string[] groupArry = new string[grouplist.Count];
            for (int i = 0; i < grouplist.Count; i++)
            {
                if (grouplist[i] != null) {
                    groupArry[i] = grouplist[i];
                }
            }
            List<Contactor> contlist = new List<Contactor>();
            contlist = (from con in CommonRep.GetQueryable<Contactor>()
                        where con.Deal == AppContext.Current.User.Deal &&
                              con.IsDefaultFlg == "1" &&
                              groupArry.Contains(con.GroupCode)
                        select con).Distinct().ToList<Contactor>();
            return contlist;
        }

        /// <summary>
        /// Get queryable history list for all customer.
        /// </summary>
        /// <returns></returns>
        public IQueryable<ContactHistory> GetContactHistory()
        {
            IQueryable<ContactHistory> li = CommonRep.GetQueryable<ContactHistory>()
                .Where(ch => ch.Deal == AppContext.Current.User.Deal)
                .OrderByDescending(a => a.ContactDate);
            return li;
        }

        public string customerNameGet(string strCustNum)
        {
            return CommonRep.GetQueryable<Customer>().Where(o => o.CustomerNum == strCustNum && o.Deal == AppContext.Current.User.Deal).Select(o => o.CustomerName).FirstOrDefault();
        }

        public IEnumerable<SendSoaHead> invoiceAgingGet(string strCustNum,string legalEntity,string condition="CC")
        {       
            string deal = AppContext.Current.User.Deal.ToString();
            string[] arrLegalEntity = legalEntity.Split(',');
            List<CustomerAging> newCusAgingList =new List<CustomerAging>();
            if (condition.Equals("CC") || condition.Equals("BPTP"))
            {
            //CustomerAging
            newCusAgingList = CommonRep.GetQueryable<CustomerAging>()
                .Where(o => o.Deal == AppContext.Current.User.Deal && o.CustomerNum == strCustNum && o.RemoveFlg == "0").ToList();
                }
            else if (condition.Equals("HC"))
            {
                newCusAgingList = CommonRep.GetQueryable<CustomerAging>()
                .Where(o => o.Deal == AppContext.Current.User.Deal && o.CustomerNum == strCustNum && o.RemoveFlg == "0" && arrLegalEntity.Contains(o.LegalEntity)).ToList();
                }
            else
            {newCusAgingList=new List<CustomerAging>();}

            //Rate
            var rateList = CommonRep.GetQueryable<RateTran>()
                .Where(o => o.Deal == AppContext.Current.User.Deal && o.EffectiveDate <= AppContext.Current.User.Now.Date && o.ExpiredDate >= AppContext.Current.User.Now.Date).ToList();
            //invoice
            var oldinvoiceList = CommonRep.GetQueryable<InvoiceAging>()
                .Where(o => o.Deal == AppContext.Current.User.Deal && o.CustomerNum == strCustNum).ToList();
            List<InvoiceAging> newinvoiceList = new List<InvoiceAging>();
            newinvoiceList = oldinvoiceList;
            foreach (var item in newinvoiceList)
            {
                if (item.Currency != "USD")
                {
                    item.StandardBalanceAmt = rateList.Find(m => m.ForeignCurrency == item.Currency).Rate * item.BalanceAmt;
                }
                else { item.StandardBalanceAmt = item.BalanceAmt; }
            }

            //cus
            Customer cus = new Customer();
            cus = CommonRep.GetQueryable<Customer>().Include<Customer, CustomerGroupCfg>(c => c.CustomerGroupCfg)
                .Where(o => o.Deal == AppContext.Current.User.Deal && o.CustomerNum == strCustNum).SingleOrDefault();

            //sendsoa
            List<SendSoaHead> sendsoaList = new List<SendSoaHead>();
            SendSoaHead sendsoa = new SendSoaHead();

            //SpecialNotes
            var SNList = CommonRep.GetQueryable<SpecialNote>().Where(o => o.Deal == AppContext.Current.User.Deal && o.CustomerNum == strCustNum).ToList();

            //customerchangehis=>class
            var classList = CommonRep.GetQueryable<CustomerLevelView>()
                .Where(o => o.Deal == AppContext.Current.User.Deal && o.CustomerNum == strCustNum).ToList();
            CustomerLevelView level = new CustomerLevelView();
                
            //agingDT
            DateTime agingDT = new DateTime();
            PeroidService pservice = SpringFactory.GetObjectImpl<PeroidService>("PeroidService");
            PeriodControl currentP = pservice.getcurrentPeroid();
            agingDT = dataConvertToDT(currentP.PeriodEnd.ToString());
            DateTime agingDT90 = new DateTime();
            agingDT90 = agingDT.AddDays(-90);

            sendsoa = new SendSoaHead();
            level = classList.Find(m => m.Deal == AppContext.Current.User.Deal && m.CustomerNum == strCustNum);
            sendsoa.Deal = AppContext.Current.User.Deal;
            sendsoa.CustomerCode = strCustNum;
            sendsoa.CustomerName = cus.CustomerName;
            sendsoa.TotalBalance = newCusAgingList.Sum(m => m.TotalAmt);
            sendsoa.CustomerClass = (string.IsNullOrEmpty(level.ClassLevel) == true ? "LV" : level.ClassLevel)
                    + (string.IsNullOrEmpty(level.RiskLevel) == true ? "LR" : level.RiskLevel);
            //sendsoa.SpecialNotes = cus.SpecialNotes;

            List<SoaLegal> sublegalList = new List<SoaLegal>();
            SoaLegal sublegal = new SoaLegal();
            foreach (var legal in newCusAgingList)
            {
                var invoiceList = newinvoiceList
                    .FindAll(m => m.Deal == AppContext.Current.User.Deal && m.CustomerNum == strCustNum && m.LegalEntity == legal.LegalEntity).OrderBy(m=>m.DueDate).ToList();
                //modify by zhangYu start
                List<InvoiceAging> invoice = new List<InvoiceAging>();
                if (condition.Equals("BPTP") ) //break PTP
                {
                     invoice = invoiceList.FindAll(m => m.States != Helper.EnumToCode<InvoiceStatus>(InvoiceStatus.Closed)
                    ).OrderBy(o => o.DueDate).OrderBy(o => o.PtpDate).OrderByDescending(o => o.States, new PTPKeyComparer()).ToList();
                }
                else if (condition.Equals("HC"))//Hold Customer
                {
                    invoice = invoiceList.FindAll(m => m.States != Helper.EnumToCode<InvoiceStatus>(InvoiceStatus.Closed)
                   ).OrderBy(o => o.DueDate).OrderBy(o => o.PtpDate).OrderByDescending(o => o.States, new BrokenPTPKeyComparer()).ToList();

                }
                else //contact customer
                { 
                    invoice = invoiceList.FindAll(m => m.States == Helper.EnumToCode<InvoiceStatus>(InvoiceStatus.Open)
                    || m.States == Helper.EnumToCode<InvoiceStatus>(InvoiceStatus.PTP) 
                    || m.States == Helper.EnumToCode<InvoiceStatus>(InvoiceStatus.Dispute)
                    || m.States == Helper.EnumToCode<InvoiceStatus>(InvoiceStatus.PartialPay)
                    || m.States == Helper.EnumToCode<InvoiceStatus>(InvoiceStatus.Broken_PTP)
                    || m.States == Helper.EnumToCode<InvoiceStatus>(InvoiceStatus.Hold)
                    || m.States == Helper.EnumToCode<InvoiceStatus>(InvoiceStatus.Payment));
                }
                //modify by zhangYu End
                sublegal = new SoaLegal();
                sublegal.LegalEntity = legal.LegalEntity;
                sublegal.Country = legal.Country;
                sublegal.CreditLimit = legal.CreditLimit;
                sublegal.TotalARBalance = legal.TotalAmt;
                sublegal.PastDueAmount = legal.TotalAmt - legal.CurrentAmt;
                sublegal.CreditBalance = invoice.FindAll(m => m.BalanceAmt < 0).Sum(m => m.BalanceAmt);
                sublegal.CurrentBalance = legal.CurrentAmt;
                sublegal.FCollectableAmount = invoice
                    .FindAll(m => m.DueDate <= agingDT && (m.Class == "DM" || m.Class == "INV")).Sum(m => m.StandardBalanceAmt);
                sublegal.FOverdue90Amount = invoice
                    .FindAll(m => m.DueDate <= agingDT90 && (m.Class == "DM" || m.Class == "INV")).Sum(m => m.StandardBalanceAmt);
                var SN = SNList.Find(m =>  m.LegalEntity == legal.LegalEntity);
                if (SN == null)
                {
                    sublegal.SpecialNotes = "";
                }
                else
                {
                    sublegal.SpecialNotes = SN.SpecialNotes;
                }
                List<SoaInvoice> subinvoiceList = new List<SoaInvoice>();
                SoaInvoice subinvoice = new SoaInvoice();
                if (invoice.Count > 0)
                {
                    foreach (var inv in invoice)
                    {
                        subinvoice = new SoaInvoice();
                        subinvoice.InvoiceId = inv.Id;
                        subinvoice.InvoiceNum = inv.InvoiceNum;
                        subinvoice.CustomerNum = inv.CustomerNum;
                        subinvoice.CustomerName = inv.CustomerName;
                        subinvoice.LegalEntity = inv.LegalEntity;
                        subinvoice.InvoiceDate = inv.InvoiceDate;
                        subinvoice.CreditTerm = inv.CreditTrem;
                        subinvoice.DueDate = inv.DueDate;
                        subinvoice.PurchaseOrder = inv.PoNum;
                        subinvoice.SaleOrder = inv.SoNum;
                        subinvoice.RBO = inv.MstCustomer;
                        subinvoice.InvoiceCurrency = inv.Currency;
                        subinvoice.OriginalInvoiceAmount = inv.OriginalAmt.ToString();
                        subinvoice.OutstandingInvoiceAmount = inv.BalanceAmt;
                        subinvoice.DaysLate = new TimeSpan(AppContext.Current.User.Now.Ticks).Subtract(new TimeSpan(Convert.ToDateTime(inv.DueDate).Ticks)).Duration().Days.ToString();
                        subinvoice.InvoiceTrack = !String.IsNullOrEmpty(inv.TrackStates) ? Helper.CodeToEnum<TrackStatus>(inv.TrackStates).ToString().Replace("_", " ") : "";
                        subinvoice.Status = !String.IsNullOrEmpty(inv.States) ? Helper.CodeToEnum<InvoiceStatus>(inv.States).ToString().Replace("_", " ") : "";
                        //added by zhangYu start
                        subinvoice.PtpDate = inv.PtpDate;
                        //added by zhangYu End
                        subinvoice.DocumentType = inv.Class;
                        subinvoice.Comments = inv.Comments;
                        subinvoiceList.Add(subinvoice);
                    }
                }
                else
                {
                    subinvoice = new SoaInvoice();
                    subinvoiceList.Add(subinvoice);
                }
                // logic to build reminder calendars
                IBaseDataService bdSer = SpringFactory.GetObjectImpl<IBaseDataService>("BaseDataService");
                IDunningService service = SpringFactory.GetObjectImpl<IDunningService>("DunningReminderService");
                List<CollectorAlert> reminders = service.GetEstimatedReminders(new List<string>() { strCustNum }, legal.LegalEntity);

                ReminderCalendar calendar = new ReminderCalendar();
                // 1. SOA
                var tracking = calendar.GetTracking(reminders.FindAll(a => a.CustomerNum == strCustNum && string.IsNullOrEmpty(a.LegalEntity)));
                // 2. Other reminders
                tracking = calendar.GetTracking(reminders.FindAll(a => a.CustomerNum == strCustNum && a.LegalEntity == legal.LegalEntity), tracking);
                // 3. Append other information shown in UI;
                bdSer.AppendTrackingConfig(tracking, deal, strCustNum, legal.LegalEntity);
                sublegal.SubTracking = tracking;

                sublegal.SubInvoice = subinvoiceList;
                sublegalList.Add(sublegal);
            }
            sendsoa.SubLegal = sublegalList;

            //contact
            //List<Contactor> contactList = CommonRep.GetQueryable<Contactor>()
            //    .Where(m => m.Deal == AppContext.Current.User.Deal && m.CustomerNum == strCustNum).Select(m => m).ToList();

            //List<SoaContact> subcontactList = new List<SoaContact>();
            //SoaContact subcontact = new SoaContact();
            //foreach (var conl in contactList)
            //{
            //    subcontact = new SoaContact();
            //    subcontact.ContactName = conl.Name;
            //    subcontact.Department = conl.Department;
            //    subcontact.Title = conl.Title;
            //    subcontact.ContactNumber = conl.Number;
            //    subcontact.Email = conl.EmailAddress;
            //    subcontact.Comment = "";
            //    subcontactList.Add(subcontact);
            //}
            //sendsoa.SubContact = subcontactList;
            //paymentbank
            //List<CustomerPaymentBank> paybankList = CommonRep.GetQueryable<CustomerPaymentBank>()
            //    .Where(m => m.Deal == AppContext.Current.User.Deal && m.CustomerNum == strCustNum).Select(m => m).ToList();
            //List<SoaPaymentBank> subpaybankList = new List<SoaPaymentBank>();
            //SoaPaymentBank subpaybank = new SoaPaymentBank();
            //foreach (var pl in paybankList)
            //{
            //    subpaybank = new SoaPaymentBank();
            //    subpaybank.AccountName = pl.BankAccountName;
            //    subpaybank.BankName = pl.BankName;
            //    subpaybank.BankAccount = pl.BankAccount;
            //    subpaybank.CreateDate = pl.CreateDate;
            //    subpaybank.CreatePerson = pl.CreatePersonId.ToString();
            //    subpaybank.InUse = pl.Flg;
            //    subpaybank.Description = pl.Description;
            //    subpaybankList.Add(subpaybank);
            //}
            //sendsoa.SubPaymentBank = subpaybankList;
            //paymentcircle
            //List<CustomerPaymentCircle> paycircleList = CommonRep.GetQueryable<CustomerPaymentCircle>()
            //    .Where(m => m.Deal == AppContext.Current.User.Deal && m.CustomerNum == strCustNum).Select(m => m).ToList();
            //List<SoaPaymentCalender> subpaycircleList = new List<SoaPaymentCalender>();
            //SoaPaymentCalender subpaycircle = new SoaPaymentCalender();
            //int sort = 1;
            //foreach (var pcl in paycircleList)
            //{
            //    subpaycircle = new SoaPaymentCalender();
            //    subpaycircle.sortId = sort;
            //    subpaycircle.PaymentDay = pcl.PaymentDay;
            //    subpaycircle.WeekDay = pcl.PaymentWeek;
            //    subpaycircleList.Add(subpaycircle);
            //    sort++;
            //}
            //sendsoa.SubPaymentCalender = subpaycircleList;

            sendsoaList.Add(sendsoa);

            return sendsoaList.AsQueryable<SendSoaHead>();
        }

        public class PTPKeyComparer : System.Collections.Generic.Comparer<string>
        {
            public override int Compare(string x, string y)
            {
                var code = Helper.EnumToCode<InvoiceStatus>(InvoiceStatus.PTP);
                if (x == code)
                {
                    if (y == code)
                    {
                        return 0;
                    }
                    else
                    {
                        return 1;
                    }
                }
                else if (y == code)
                {
                    return -1;
                }
                else
                {
                    return x.CompareTo(y);
                }
            }
        }

        public class BrokenPTPKeyComparer : System.Collections.Generic.Comparer<string>
        {
            public override int Compare(string x, string y)
            {
                var code = Helper.EnumToCode<InvoiceStatus>(InvoiceStatus.Broken_PTP);
                if (x == code)
                {
                    if (y == code)
                    {
                        return 0;
                    }
                    else
                    {
                        return 1;
                    }
                }
                else if (y == code)
                {
                    return -1;
                }
                else
                {
                    return x.CompareTo(y);
                }
            }
        }

        public DateTime dataConvertToDT(string strData)
        {
            DateTime dt = new DateTime();
            if (!string.IsNullOrEmpty(strData.Trim()))
            {
                return Convert.ToDateTime(strData);
            }

            return dt;
        }

        /// <summary>
        /// Insert Datas To Invoice_Log Table (Notice)
        /// </summary>
        /// <param name="list">list</param>
        public void insertInvoiceLogForNotice(List<string> list) 
        {
            List<InvoiceLog> listInvLog = new List<InvoiceLog>();
            InvoiceLog invLog = new InvoiceLog();
            List<string> invoiceIds = new List<string>();
            int id = 0;
            ISoaService service = SpringFactory.GetObjectImpl<ISoaService>("SoaService");
            try
            {
                invoiceIds = list[1].Split(',').ToList();

                for (int i = 0; i < invoiceIds.Count; i++)
                {
                    id = Int32.Parse(invoiceIds[i]);
                    InvoiceAging invAging = CommonRep.GetDbSet<InvoiceAging>().Where(o => o.Id == id).FirstOrDefault();

                    invLog = new InvoiceLog();
                    invLog.InvoiceId = invAging.InvoiceNum;
                    invLog.Deal = AppContext.Current.User.Deal;
                    invLog.CustomerNum = invAging.CustomerNum;//list[2];
                    invLog.LogDate = AppContext.Current.User.Now;
                    invLog.LogPerson = AppContext.Current.User.EID;
                    invLog.LogAction = "CONTACT";
                    invLog.LogType = "5";
                    invLog.OldStatus = invAging.States;
                    invLog.NewStatus = Helper.EnumToCode<InvoiceStatus>(InvoiceStatus.Payment);
                    invLog.OldTrack = invAging.TrackStates;
                    string trackName = list[5].Replace(" ", "_");
                    string trackCode = "";
                    if (trackName == TrackStatus.Payment_Notice_Received.ToString()) { 
                        trackCode = Helper.EnumToCode<TrackStatus>(TrackStatus.Payment_Notice_Received);
                    }
                    else if (trackName == TrackStatus.Contra.ToString())
                    {
                        trackCode = Helper.EnumToCode<TrackStatus>(TrackStatus.Contra);
                    }
                    else if (trackName == TrackStatus.Breakdown.ToString()) 
                    {
                        trackCode = Helper.EnumToCode<TrackStatus>(TrackStatus.Breakdown);
                    }
                    invLog.NewTrack = trackCode;
                    invLog.ProofId = list[3];
                    invLog.ContactPerson = list[4];
                    invLog.Discription = list[6] + Environment.NewLine + invAging.Comments;
                    listInvLog.Add(invLog);

                    //update track_status(invoice_aging)
                    invAging.TrackStates = Helper.EnumToCode<TrackStatus>(TrackStatus.Payment_Notice_Received);
                    invAging.States = Helper.EnumToCode<InvoiceStatus>(InvoiceStatus.Payment);
                    invAging.TrackStates = trackCode;
                    invAging.Comments = list[6] + Environment.NewLine + invAging.Comments;
                }
                CommonRep.AddRange<InvoiceLog>(listInvLog);
                CommonRep.Commit();
            }
            catch (Exception ex) 
            {
                throw ex;
            }
        }

        /// <summary>
        /// Insert Datas To Invoice_Log Table (PTP)
        /// </summary>
        /// <param name="list">list</param>
        public void insertInvoiceLogForPtp(List<string> list)
        {
            List<InvoiceLog> listInvLog = new List<InvoiceLog>();
            InvoiceLog invLog = new InvoiceLog();
            List<string> invoiceIds = new List<string>();
            int id = 0;

            try
            {
                invoiceIds = list[1].Split(',').ToList();

                for (int i = 0; i < invoiceIds.Count; i++)
                {
                    id = Int32.Parse(invoiceIds[i]);
                    InvoiceAging invAging = CommonRep.GetDbSet<InvoiceAging>().Where(o => o.Id == id).FirstOrDefault();
                    
                    invLog = new InvoiceLog();
                    invLog.InvoiceId = invAging.InvoiceNum;
                    invLog.Deal = AppContext.Current.User.Deal;
                    invLog.CustomerNum = invAging.CustomerNum;
                    invLog.LogDate = AppContext.Current.User.Now;
                    invLog.LogPerson = AppContext.Current.User.EID;
                    invLog.LogAction = "CONTACT";
                    invLog.LogType = "4";
                    invLog.OldStatus = invAging.States;
                    invLog.NewStatus = Helper.EnumToCode<InvoiceStatus>(InvoiceStatus.PTP);
                    invLog.OldTrack = invAging.TrackStates;
                    invLog.NewTrack = Helper.EnumToCode<TrackStatus>(TrackStatus.PTP);
                    invLog.ProofId = list[3];
                    invLog.ContactPerson = list[4];
                    invLog.Discription = list[5] + Environment.NewLine + invAging.Comments;
                    listInvLog.Add(invLog);

                    //update status and ptpDate(invoice_aging)
                    invAging.States = Helper.EnumToCode<InvoiceStatus>(InvoiceStatus.PTP);
                    invAging.TrackStates = Helper.EnumToCode<TrackStatus>(TrackStatus.PTP);
                    invAging.PtpDate = DateTime.Parse(list[6]);
                    invAging.Comments = list[5] + Environment.NewLine + invAging.Comments;
                }
                CommonRep.AddRange<InvoiceLog>(listInvLog);
                CommonRep.Commit();
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// Insert Datas To Invoice_Log Table (Dispute)
        /// </summary>
        /// <param name="disInvInstance"></param>
        public void insertInvoiceLogForDispute(DisputeInvoice disInvInstance)
        {
            InvoiceLog invLog = new InvoiceLog();
            DisputeInvoice disInv = new DisputeInvoice();
            List<InvoiceLog> listInvLog = new List<InvoiceLog>();
            List<DisputeInvoice> listDisInvoice = new List<DisputeInvoice>();
            int id = 0;
            string tempCustNum = "";
            try
            {
                int disputeId = 0;

                for (int i = 0; i < disInvInstance.invoiceIds.Length; i++)
                {
                    id = disInvInstance.invoiceIds[i];
                    InvoiceAging invAging = CommonRep.GetDbSet<InvoiceAging>().Where(o => o.Id == id).FirstOrDefault();

                    //insert t_dispute table
                    if (tempCustNum.IndexOf(invAging.CustomerNum) < 0) 
                    {
                        tempCustNum += invAging.CustomerNum + ",";
                        disputeId = this.insertDispute(disInvInstance, invAging.CustomerNum);
                    }

                    //insert invoice log
                    invLog = new InvoiceLog();
                    invLog.InvoiceId = invAging.InvoiceNum;
                    invLog.Deal = AppContext.Current.User.Deal;
                    //invLog.CustomerNum = disInvInstance.customerNum;
                    //update by pxc
                    invLog.CustomerNum = invAging.CustomerNum;
                    invLog.LogDate = AppContext.Current.User.Now;
                    invLog.LogPerson = AppContext.Current.User.EID;
                    invLog.LogAction = "CONTACT";
                    invLog.LogType = "3";
                    invLog.OldStatus = invAging.States;
                    invLog.NewStatus = Helper.EnumToCode<InvoiceStatus>(InvoiceStatus.Dispute);
                    invLog.OldTrack = invAging.TrackStates;
                    invLog.NewTrack = Helper.EnumToCode<TrackStatus>(TrackStatus.Dispute);
                    invLog.ContactPerson = disInvInstance.contactPerson;
                    invLog.ProofId = disInvInstance.contactId;
                    invLog.Discription = disInvInstance.comments + Environment.NewLine + invAging.Comments;
                    listInvLog.Add(invLog);

                    //insert dispute_invoice
                    disInv = new DisputeInvoice();
                    disInv.InvoiceId = invAging.InvoiceNum;
                    disInv.DisputeId = disputeId;
                    listDisInvoice.Add(disInv);

                    //update status(invoice_aging) 
                    invAging.States = Helper.EnumToCode<InvoiceStatus>(InvoiceStatus.Dispute);
                    invAging.TrackStates = Helper.EnumToCode<TrackStatus>(TrackStatus.Dispute);
                    invAging.Comments = disInvInstance.comments + Environment.NewLine + invAging.Comments;

                }
                CommonRep.AddRange<InvoiceLog>(listInvLog);
                CommonRep.AddRange<DisputeInvoice>(listDisInvoice);
                CommonRep.Commit();
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// insert t_dispute table
        /// </summary>
        /// <param name="disInvInstance"></param>
        public int insertDispute(DisputeInvoice disInvInstance,string customerNum) {
            Dispute dispute = new Dispute();
            DisputeHis disHis = new DisputeHis();
            List<DisputeHis> listDisHis = new List<DisputeHis>();

            try
            {
                //insert dispute
                Customer customer = CommonRep.GetDbSet<Customer>().Where(o => o.CustomerNum == customerNum).FirstOrDefault();
                dispute.Deal = AppContext.Current.User.Deal;
                dispute.Eid = customer.Collector;
                dispute.CustomerNum = customerNum;
                dispute.IssueReason = disInvInstance.issue;
                dispute.CreateDate = AppContext.Current.User.Now;
                dispute.Status = Helper.EnumToCode<DisputeStatus>(DisputeStatus.Open);
                dispute.CreatePerson = AppContext.Current.User.EID;
                dispute.Comments = disInvInstance.comments;
                CommonRep.Add(dispute);
                CommonRep.Commit();
                int id = dispute.Id;

                //insert dispute_his
                disHis.DisputeId = id;
                disHis.HisType = Helper.EnumToCode<DisputeStatus>(DisputeStatus.Open);
                disHis.HisDate = dispute.CreateDate;
                disHis.EmailId = disInvInstance.contactId;
                listDisHis.Add(disHis);
                CommonRep.AddRange<DisputeHis>(listDisHis);
                CommonRep.Commit();

                return id;
            }
            catch (Exception ex) 
            {
                throw ex;
            }
        }

        /// <summary>
        /// insert into contact_his
        /// </summary>
        /// <param name="Type">ContactType: 1:mail;2:call</param>
        /// <param name="contactors">customernums</param>
        /// <param name="Contactors">contactors</param>
        public List<ContactHistory> AddContactHistoryList(string[] contactors, string contactTo, string proofId,string inputAlertType, Action<ContactHistory> supplymentCallBack)
        {
            string deal = AppContext.Current.User.Deal.ToString();
            string eid = AppContext.Current.User.EID.ToString();
            DateTime operDT = AppContext.Current.User.Now;
            //####### add by pxc for alertType ############ s 
            int alertType = 1;
            if (inputAlertType == "001") { 
            } else if (inputAlertType == "002") {
                alertType = 2;
            } else if (inputAlertType == "003") {
                alertType = 3; 
            }
            //####### add by pxc for alertType ############ e
            var alertList = CommonRep.GetDbSet<CollectorAlert>()
                .Where(o => o.Deal == deal && o.AlertType == alertType && contactors.Contains(o.CustomerNum) && o.PeriodId == CurrentPeriod).ToList();
            List<ContactHistory> chisList = new List<ContactHistory>();
            ContactHistory chis = new ContactHistory();
            foreach (var cus in contactors)
            {
                CollectorAlert alert = alertList.FindAll(m => m.CustomerNum == cus).FirstOrDefault();
                chis = new ContactHistory();
                chis.Deal = deal;
                chis.LegalEntity = "";
                chis.CustomerNum = cus;
                chis.CollectorId = eid;
                chis.ContacterId = contactTo;
                chis.ContactDate = operDT;
                chis.Comments = "";
                chis.AlertId = alert == null ? 0 : alert.Id;
                chis.ContactId = proofId;
                supplymentCallBack(chis);
                chisList.Add(chis);
            }
            //using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required, new TimeSpan(0, 30, 0)))
            //{
            //(CommonRep.GetDBContext() as OTCEntities).BulkInsert(chisList);
            //    scope.Complete();
            //}
            return chisList;
        }

        public void AddMailContactHistory(string contactor, string contactTo, string proofId)
        {
            List<ContactHistory> chisList = new List<ContactHistory>();
            ContactHistory chis = new ContactHistory();
            chis.Deal = AppContext.Current.User.Deal;
            chis.LegalEntity = "";
            chis.CustomerNum = contactor;
            chis.CollectorId = AppContext.Current.User.EID;
            chis.ContacterId = contactTo;
            chis.ContactDate = AppContext.Current.User.Now;
            chis.Comments = "";
            chis.ContactId = proofId;
            chis.ContactType = "Mail";
            CommonRep.Add(chis);
            CommonRep.Commit();
        }
        public void AddOrUpdateDomain(ContactorDomain cont)
        {
            try
            {
                if (cont.Id == 0)
                {
                    cont.Deal = AppContext.Current.User.Deal;
                    CommonRep.Add(cont);
                }
                else
                {
                    ContactorDomain old = CommonRep.FindBy<ContactorDomain>(cont.Id);
                    ObjectHelper.CopyObjectWithUnNeed(cont, old, new string[] { "Id", "Customer" });
                }
                CommonRep.Commit();
            }
            catch (Exception ex)
            {
                Helper.Log.Info(ex);
                throw new Exception(ex.Message);
            }
        }

        public void DeleteDomain(int id)
        {
            // AssertUtils.IsTrue(id > 0, "Contact Id");

            ContactorDomain old = CommonRep.FindBy<ContactorDomain>(id);
            if (old != null)
            {
                CommonRep.Remove(old);
                CommonRep.Commit();
            }
        }

    }
}
